import React, { useRef, useEffect, useState, useImperativeHandle } from 'react';
import { Select, Space, Input, message, Button, Form } from 'antd';
import { CmdbContent, CmdbHeader, useModelAssociateType, NameSpaceBtn, Authorized } from '@/components';
import cmdbres from '@/data/cmdbres';
import request from '@/utils/request';
import permission from '@/config/permission';
import './index.less';
import G6 from '@antv/g6';
import registerEdge from './config/register-edge';
import registerNode from './config/register-node';
import { G6ToolBar, G6Menu, G6Legend } from './config/register-plugins';
import { defaultNodeConfig, defaultEdgeConfig, defaultLayout } from './config/default';
import { initData } from './config/utils';
import { nodeMouseFn } from '@/modules/topology/utils';
import HelpTipModal from './components/helpTipModal';
import DetailsModal from '../components/detailsModal';
import CreateModel from './components/createModel';
const GRAPH_ID = 'model-graph-container';
// import mockData from './mock.json';

const modelTopology = ({ history, match, location, cRef, modelInfo }) => {
    const domRef = useRef(null);
    const graphRef = useRef(null);
    let graph = graphRef.current;
    const [showHelp, setShowHelp] = useState(false);
    const [detailInfo, setDetailInfo] = useState({});
    const [showDetailModal, setShowDetailModal] = useState(false);
    const [showAddNodeModal, setShowAddNodeModal] = useState(false);
    const [{ associateType }, loading] = useModelAssociateType(); // 翻译关联关系
    const [topoData, setTopoData] = useState();

    const [addNum, setAddNum] = useState(0);
    const [curEdge, setCurEdge] = useState(null);
    const [level, setLevel] = useState(1);

    useEffect(() => {
        if (modelInfo) {
            fetchData();
        }
    }, [modelInfo, level]);

    const fetchData = async () => {
        const fn = [];
        if (modelInfo.moduleCode == 'biz') {
            fn.push(queryMainLine());
        } else {
            fn.push(queryAllModelAssociate());
        }
        const [edges] = await Promise.all(fn);
        if (edges) {
            setTopoData({ nodes: edges, edges });
        }
    };

    const queryModel = async () => {
        try {
            let res = await request({
                ...cmdbres.queryModelList,
                params: {
                    namespace: 'default',
                },
            });
            return res && res.data ? res.data : [];
        } catch (error) {
            return [];
        }
    };

    const queryAllModelAssociate = async () => {
        try {
            const res = await request({
                ...cmdbres.queryModelAssociate(modelInfo.cmModuleId, level),
                params: {
                    pageSize: Number.MAX_SAFE_INTEGER,
                    pageNumber: 1,
                    sort: {
                        create_time: 'DESC',
                    },
                },
            });
            return res && res.data ? res.data : [];
        } catch (error) {
            return [];
        }
    };
    //查询拓扑组成的模型关系
    const queryMainLine = async () => {
        try {
            const res = await request({
                ...cmdbres.queryMainLine,
                params: {},
            });
            let arr = [];
            if (res && res.data) {
                res.data.map((item) => {
                    if (item.nextModuleId) {
                        arr.push({
                            srcModuleId: item.nextModuleId,
                            srcModuleCode: item.nextModuleCode,
                            srcModuleName: item.nextModuleName,
                            destModuleId: item.moduleId,
                            destModuleCode: item.moduleCode,
                            destModuleName: item.moduleName,
                            associateType: '拓扑组成',
                        });
                    }
                });
            }
            return arr;
        } catch (error) {
            console.log(error);
        }
    };

    useEffect(() => {
        fetchLayout();

        return () => {
            if (graph) {
                graph.destroy();
            }
        };
    }, [associateType, topoData]);

    const fetchLayout = async () => {
        if (!(associateType && topoData)) return;
        const data = initData(topoData, associateType, modelInfo);

        createGraphic().then((res) => {
            graph = res;
            graph.read(data);
            // 关闭局部渲染解决缩放或者拖拽引起的残影问题（关闭会影响性能，临时解决办法）
            graph.get('canvas').set('localRefresh', false);
            bindEvents();
        });
    };

    const createGraphic = async () => {
        // 注册自定义节点
        registerEdge(G6);
        // 注册自定义边
        registerNode(G6);

        const container = document.getElementById(GRAPH_ID);
        const tree = new G6.Graph({
            container: domRef.current,
            width: container.offsetWidth,
            height: container.offsetHeight,
            fitCenter: true,
            defaultNode: defaultNodeConfig,
            defaultEdge: defaultEdgeConfig,
            layout: defaultLayout,
            animate: true,
            modes: {
                default: ['drag-canvas', 'drag-node', 'zoom-canvas'],
            },
            plugins: [
                new G6.Grid(),
                new G6.Minimap({
                    size: [200, 150],
                }),
                G6Menu(G6, menuHandles),
                G6ToolBar(G6),
            ],
        });

        graphRef.current = tree;
        return tree;
    };

    const bindEvents = () => {
        graph.on('node:mouseenter', (evt) => nodeMouseFn(evt, true, graph));
        graph.on('node:mouseleave', (evt) => nodeMouseFn(evt, false, graph));

        graph.on('edge:mouseleave', (evt) => {
            const edge = evt.item;
            graph.setItemState(edge, 'hover', false);
        });
        graph.on('canvas:click', (evt) => {
            graph.getNodes().forEach((node) => {
                graph.clearItemStates(node);
            });
        });
        graph.on('edge:click', (evt) => {
            const { item, target } = evt;
            if (target.cfg.name == 'add-node-shape') {
                setCurEdge(evt);
                setShowAddNodeModal(true);
            }
        });
        graph.on('node:click', (evt) => {
            const { item, target } = evt;
            if (target.cfg.name == 'child-icon-shape') {
                console.log(item);
            }
        });
    };
    const menuHandles = {
        queryDetail(item) {
            const model = item.getModel();
            setDetailInfo(model);
            setShowDetailModal(true);
        },
    };

    useImperativeHandle(cRef, () => ({
        onRefresh: async () => {
            fetchData();
        },
    }));

    return (
        <>
            <div className="affix-header">
                <div className="header-box">
                    <Authorized authority={permission.modelRelation_edit} noMatch={null}>
                        <Button
                            type="primary"
                            icon={<span className="iconfont icon-edit"></span>}
                            onClick={() => {
                                history.push({
                                    pathname: `/model/topology/${modelInfo.cmModuleId}`,
                                    state: {
                                        moduleCode: modelInfo.moduleCode,
                                        moduleName: modelInfo.moduleName,
                                        cmModuleId: modelInfo.cmModuleId,
                                        isAdd: true,
                                    },
                                });
                            }}
                        >
                            编辑拓扑
                        </Button>
                    </Authorized>
                    <div className="level">
                        <div className="name">展示层级：</div>
                        <Select
                            placeholder="请选择"
                            style={{ width: '120px' }}
                            getPopupContainer={(triggerNode) => triggerNode.parentElement}
                            value={level}
                            onChange={(value, option) => {
                                setLevel(value);
                            }}
                        >
                            {[1, 2, 3, 4, 5].map((item) => (
                                <Select.Option key={item} value={item}>
                                    {item}
                                </Select.Option>
                            ))}
                        </Select>
                    </div>
                </div>
            </div>
            <div style={{ width: '100%', height: 710, position: 'relative' }}>
                <div ref={domRef} id={GRAPH_ID} style={{ width: '100%', height: 'calc(100% - 74px)' }}></div>
                <HelpTipModal visible={showHelp} setVisible={setShowHelp} />
                <DetailsModal visible={showDetailModal} setVisible={setShowDetailModal} info={detailInfo} />
                <CreateModel
                    visible={showAddNodeModal}
                    setVisible={setShowAddNodeModal}
                    onCreateFinish={fetchData}
                    edge={curEdge}
                />
            </div>
        </>
    );
};

export default modelTopology;
